package restaurant.gui;

import jade.core.ProfileImpl;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import jade.wrapper.StaleProxyException;

import java.awt.BorderLayout;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.WindowConstants;

import restaurant.core.Meal;
import restaurant.core.MealType;
import restaurant.core.Portata;
import restaurant.core.Restaurant;

/**
 * Graphic interface, allow to create the environment configuration 
 * and display the sequence of actions performed by the agent
 *
 */
public class MainJFrame extends javax.swing.JFrame {

	private static final long serialVersionUID = 1L;
	
	public GridPanel gridPanel;
	public SettingsPanel settingsPanel;
	
	int size = 6;
	int num_waiter = 0;
	int num_customer = 0;
	
	public Environment env;
	
	Vector<Agent> agents;
	
	protected boolean stopped = true;
	
	//TODO: bisogna inizializzarlo quando si preme il pulsante play
	public Restaurant restaurant;
	
	private jade.core.Runtime rt = jade.core.Runtime.instance();
	private ProfileImpl p = new ProfileImpl();
	private AgentContainer cc = rt.createMainContainer(p);
	
	public static void main(String[] args) {
		new MainJFrame();
	}
	
	public MainJFrame() {
		super();
		
		initGUI();
	}
	
	/**
	 * Generate a default configuration 
	 * 		Set the display Layout and menu component.
	 * 		Create a default configuration, set the agent on position 0,0 
	 * 		and the environment as static.
	 */
	private void initGUI() {
		setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		
		agents = new Vector<Agent>();
		
		env = new Environment(size, size);
		env.initialize(this);

		settingsPanel = new SettingsPanel(this);
		getContentPane().add(settingsPanel, BorderLayout.WEST);

		gridPanel = new GridPanel(this, env);
		getContentPane().add(gridPanel, BorderLayout.CENTER);
		
		pack();
		this.setVisible(true);
	}

    /**
     * Execute a loop until the goal is reached and 
     * the max number of step (opBound) is not reached
     */
	public void mainLoop(){
		env.show();
		
		for(Agent a : agents)
			a.actionList.clear();

//		for(Agent a : agents)
//			if(a.type == Square.Type.CUSTOMER)
//				System.out.println("CustomerAgent goal reached " + a.goalReached());
//			else
//				System.out.println("WaiterAgent goal reached " + a.goalReached());
//		
//		System.out.println("stopped " + stopped);

		while(!stopped){
			for(Agent a : agents)
				if(a.goalReached())
					return;
			env.update();
			env.show();
			gridPanel.update();
			settingsPanel.update();
		}
		stopped = true;
		settingsPanel.update();
		settingsPanel.report();
	}
	
	/**
     * Execute only a loop
     */
	public void mainLoopOnes(){
	}
	
	public void addCustomer(String customerName) {
		Object[] params = {this};
		AgentController customerController;
		try {
			customerController = cc.createNewAgent(customerName, "restaurant.agents.CustomerAgent", params);
			customerController.start();
			while(customerController.getState().getCode() != 2);
		} catch (StaleProxyException e) {
			e.printStackTrace();
		}
	}
	
	public void startRestaurant(int numTables, int numWaiters, int numCustomer, Hashtable<Integer, Coordinate> tablesCoordinates, Meal[] meals) {
		Meal[] tmpMeals = {
				new Meal("mare", 5, Portata.ANTIPASTO, MealType.PESCE),
				new Meal("pasta", 3, Portata.FIRST, MealType.CARNE),
				new Meal("secondo di carne", 4, Portata.SECOND, MealType.CARNE),
				new Meal("secondo di pesce", 7, Portata.SECOND, MealType.PESCE),
				new Meal("torta", 3, Portata.DESSERT, MealType.DOLCE),
				new Meal("mela", 1, Portata.FRUIT, MealType.VERDURA)
			};
			
		this.restaurant = Restaurant.getInstance(numTables, tmpMeals, numWaiters, tablesCoordinates);
		
		if (meals != null) {
			tmpMeals = meals;
			this.restaurant = Restaurant.getInstance(numTables, tmpMeals, numWaiters, tablesCoordinates);
		}
		try {
			{
				AgentController bookingController = cc.createNewAgent("booking", "restaurant.agents.BookingAgent", null);
				bookingController.start();
				while(bookingController.getState().getCode() != 2);
			}

			{
				AgentController kitchenController = cc.createNewAgent("kitchen", "restaurant.agents.KitchenAgent", null);
				kitchenController.start();
				while(kitchenController.getState().getCode() != 2);
			}

			{
				AgentController masterWaiterController = cc.createNewAgent("master", "restaurant.agents.MasterWaiterAgent", null);
				masterWaiterController.start();
				while(masterWaiterController.getState().getCode() != 2);
			}
			
			{
				//the first parameter is useful to interact with gui
				//the second parameter is the experience
				//the third parameter is the minimum experience to become professional
				Object params[] = {this, 100, 50};
				for(int i = 0; i < numWaiters; i++) {
					AgentController waiterController = cc.createNewAgent("waiter" + i, "restaurant.agents.WaiterAgent", params);
					waiterController.start();
					while(waiterController.getState().getCode() != 2);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}